function VirtualtelescopeAssistant() {
	/** this is the creator function for your scene assistant object. It will be passed all the 
	*   additional parameters (after the scene name) that were passed to pushScene. The reference
	*   to the scene controller (this.controller) has not be established yet, so any initialization
	*   that needs the scene controller should be done in the setup function below.
	*/
}

/** this function is for setup tasks that have to happen when the scene is first created 
*/
VirtualtelescopeAssistant.prototype.setup = function() {
	/** use Mojo.View.render to render view templates and add them to the scene, if needed.
	 */
	
	/** setup widgets here-
	 * Instantiates UI widgets for login scene. Each widget requires attributes and a model.
	 * These are passed to the widget in a JSON object.
	 */
	this.controller.setupWidget('location-activity-spinner', 
	this.locationSpinnerAttributes = {spinnerSize: Mojo.Widget.spinnerLarge}, {});
	this.shakeCounter = 0;
	this.gpsData = {};
	
	/** add event handlers to listen to events from widgets
	 * In this case, the accelerometer is read by adding a listener to the document
	 * for the 'orientationchange' event. When handleOrientation is called, it will be
	 * passed a JSON object with the accelerometer pitch, roll, and position.
	 */
	this.handleOrientation = this.handleOrientation.bindAsEventListener(this);
}

/**This function waits for user input by means of orientation change, and then
 *activates a busy spinner ultimately waiting for the end findMe call.
 *
 *
 */
VirtualtelescopeAssistant.prototype.activate = function(event) {
	/** put in event handlers here that should only be in effect when this scene is active. For
	 * example, key handlers that are observing the document
	 * When the scene is activated, start the event listeners for taps on the 
	 * 'Star Map', 'Virtual Telescope', and 'Satellite Tracking' buttons.
	 */
	  Mojo.Event.listen(document,'orientationchange',this.handleOrientation);
	  //this.controller.listen(document, 'orientationchange', this.handleOrientation);
	  //this.controller.get("accel_data_position").update("Loading accelerometer...");
	  //this.getURLFromAngle(10);
	  this.controller.get('location-activity-spinner').mojo.start()
	  this.findMe();
}
/** remove any event handlers you added in activate and do any other cleanup that should happen before
	  * this scene is popped or another scene is pushed on top
	  */
VirtualtelescopeAssistant.prototype.deactivate = function(event) {
	
	 //Mojo.Event.stopListening(document,'orientationchange',this.handleOrientation);
}
/** this function should do any cleanup needed before the scene is destroyed as
	 *  a result of being popped off the scene stack
	 */
VirtualtelescopeAssistant.prototype.cleanup = function(event) {
	
}
/** This is the callback function for  finding your location.  Once activated it
 *starts a busy spinner on the screen while getting location data.
 *@param data The location data for the current device.
	 *
	 */
VirtualtelescopeAssistant.prototype.locationCallback = function(data) {
	var locationResponse;
	switch (data.errorCode) {
					case 0:
						locationResponse = "Latitude: " + data.latitude + "\n" + "Longitude: " + data.longitude;
						break;
					case 1:
						locationResponse = "GPS Timeout.";
						break;
					case 2:
						locationResponse = "Position Unavailable.";
						break;
					case 5:
						locationResponse = "Location services are turned off.";
						break;					
					default:
						locationResponse = "Location error: " + data.errorCode;
						break;
				}
				this.controller.get('overlay-scrim').show();
				this.controller.get('location-activity-spinner').mojo.start();
				/*
				this.controller.showAlertDialog({
				    title: $L("Current Lat/Long"),
				    message: $L(locationResponse),
					choices:[{label:$L('Ok')}]
				});
				*/
				if (data.errorCode == 0) {
					this.gpsData = data;
					this.controller.get('location-activity-spinner').mojo.stop();
					this.controller.get('overlay-scrim').hide();
				}
				else {
					this.controller.showAlertDialog({
				    	title: $L("GPS Error"),
				    	message: $L('Please try again.'),
						choices:[{label:$L('Ok')}]
					});
					this.controller.stageController.popScene();
				}
}

/**This function displays a busy spinner while querying the palm database for gps
 *location.  Then it calls it's callback function with that data.
 *
 */
VirtualtelescopeAssistant.prototype.findMe = function(event) {
	this.controller.get('overlay-scrim').show();
	this.controller.get('location-activity-spinner').mojo.start();
	this.controller.serviceRequest('palm://com.palm.location', {
		method:"getCurrentPosition",
		parameters:{accuracy: 'Medium', maximumAge: 10, responseTime: 1},
		onSuccess: function( data ) 
			{
				this.locationCallback(data);
			}.bind(this),
		onFailure: function( data )
			{
				this.locationCallback(data);
			}.bind(this),
		}
	);
}

/**This function is called when the accelerometer listener receives an event.
 * The accelerometer pitch, roll, and position are passed as parameters and
 * placed in the scene as text. Once the imageviewer API is added, this will allow
 * the user to tilt the device, and have the 'virtual telescope' window tilt in response.
 * @param {JSON Object} event
 */
VirtualtelescopeAssistant.prototype.handleOrientation = function(event) {
	var position = ["Flat, face up","Flat, face down", "Upright", "Upside Down", "Pointed left", "Pointed right"]
	//this.controller.get("accel_data_position").update("Current orientation is: " + position[event.position]);
	//this.controller.get("accel_data").update("Pitch: " + event.pitch + ", Roll: " + event.roll);
	if (event.position == 3 || event.position == 2 || event.position == 1 || event.position == 0) {
		angle = event.pitch + 90;
		this.getURLFromAngle(angle);
	} else {
		this.holdInCorrectPosition(position[event.position]);
	}
};

/** This function makes sure the user is holding the phone in the correct orientation.
 * If they aren't it gives them an error until they do.
 * @param position The device's current orientation.
 */
VirtualtelescopeAssistant.prototype.holdInCorrectPosition = function(position) {
	if (this.shakeCounter >= 10) {
		this.controller.get("telescope_img").src='images/x.jpg';
		this.controller.get("error").update("Please hold phone upright.")
		this.shakeCounter = 0;
	} else {
		this.shakeCounter++;
	}
}

/** This function retrieves variable angle and ultimately calls getURL with the
 * GPS data.
 * @param angle Current angle from horizon.
 */
VirtualtelescopeAssistant.prototype.getURLFromAngle = function(angle) {
	if (this.shakeCounter >= 10) {
		this.gpsData.angle = angle;
		this.controller.get("telescope_img").src=this.getURL(this.gpsData);
		this.controller.get("error").update("Lat: " + this.gpsData.latitude + ", Long: " + this.gpsData.longitude);
		this.shakeCounter = 0;
	} else {
		this.shakeCounter++;
	}
}


/** This function finds the current sky above the user.
 * @param UI User data
 * @return url The url to query the sky-map database.
 */
VirtualtelescopeAssistant.prototype.getURL = function(UI){
	var RA = this.locateSkyAbove(UI.latitude,UI.longitude);
    var DEC = UI.latitude;
    var url = "http://server1.sky-map.org/map?custom=1&language=EN&type=PART&w=300&h=300&angle=5.0&rotation=0.0&mag=7.5&max_stars=100000&borders=1&border_color=400000&show_grid=1&grid_color=404040&grid_color_zero=808080&grid_lines_width=1.0&grid_ra_step=1.0&grid_de_step=15.0&show_const_lines=1&constellation_lines_color=006000&constellation_lines_width=1.0&show_const_names=1&constellation_names_color=006000&const_name_font_type=PLAIN&const_name_font_name=SanSerif&const_name_font_size=15&show_const_boundaries=1&constellation_boundaries_color=000060&constellation_boundaries_width=1.0&background_color=000000&output=PNG&";
    if (UI.angle){DEC=this.updateDec(DEC,UI.angle);}
	if (!UI.zoom){UI.zoom=2;}
    url=url+"ra="+RA + "&de="+DEC+"&zoom="+UI.zoom;
    return url;
}

/** Updates declination due to angle.
 * @param declination Current declination.
 * @param angle Current angle from horizon.
 * @return newDec The new declination based on angle.
 */
VirtualtelescopeAssistant.prototype.updateDec = function(declination, angle){
	return (declination-(angle/100));
}

/** Finds the celestial coordinates for the sky above the user.
 * @param latt Current latitude.
 * @param lonn Current longitude.
 * @return newRA The new right ascension given latitude and longitude.
 */
VirtualtelescopeAssistant.prototype.locateSkyAbove = function(latt, lonn)
{
	var skyLat=latt;
	var skyLon=lonn;
	var time;
	var timeZone;
	if(skyLat&&skyLon)
    {
        var lat=parseFloat(skyLat);
        var lon=parseFloat(skyLon);
        var time=new Date();
        var timeZone=parseFloat(time.getTimezoneOffset()/60);
        var newRA=this.sidereal_time(time.getYear(),time.getMonth(),time.getDate(),time.getHours(),time.getMinutes(),time.getSeconds(),'SIDEREAL_LAST',lon);
        newRA+=timeZone;
        if(newRA<0)
            newRA+=24;
        else if(newRA>=24)
            newRA-=24;

        return newRA;
    }
    return 0;

}

/** Finds sidereal time compared to Grenich.
 */
VirtualtelescopeAssistant.prototype.sidereal_time = function(time_now_tm_year,time_now_tm_mon,time_now_tm_day,time_now_tm_hour,time_now_tm_min,time_now_tm_sec,type,longitude)
{
        var JD_J2000,JD_now,JD_diff;
        var gmst,gast,JC,eqtime,last,lmst;
        time_ref_tm_sec=0;
        time_ref_tm_min=0;
        time_ref_tm_hour=12;
        time_ref_tm_day=1;
        time_ref_tm_mon=0;
        time_ref_tm_year=100;
        JD_J2000=this.julian_date(time_ref_tm_year,time_ref_tm_mon,time_ref_tm_day,time_ref_tm_hour,time_ref_tm_min,time_ref_tm_sec);
        JD_now=this.julian_date(time_now_tm_year,time_now_tm_mon,time_now_tm_day,time_now_tm_hour,time_now_tm_min,time_now_tm_sec);
        JD_diff=JD_now-JD_J2000;
        JC=JD_diff/36525.0;
        gmst=280.46061837+360.98564736629*JD_diff+0.0003887933*Math.pow(JC,2)-Math.pow(JC,3)/38710000.0;
        while(gmst>=360.0)
            gmst-=360.0;
        gmst=gmst/15.0;
        if(type=='SIDEREAL_GMST')
            return(gmst);
        var day_of_year=this.FDoY(time_now_tm_year,time_now_tm_mon+1,time_now_tm_day);
        eqtime=(-0.49+0.3*day_of_year/365.0+0.07*Math.cos(2.0*6.2831853*(day_of_year-35.0)/365.0))/3600.0;
        gast=gmst+eqtime;
        while(gast>24.0)
            gast-=24.0;
        if(type=='SIDEREAL_GAST')
            return gast;
        last=gast+24.0+longitude/15.0;
        while(last>24.0)
            last-=24.0;
        if(type=='SIDEREAL_LAST')
            return last;
        lmst=gmst+24.0+longitude/15.0;
        while(lmst>24.0)
            lmst-=24.0;
        if(type=='SIDEREAL_LMST')
            return lmst;
        return lmst;
    }

   /** Finds current Julian date for the day.
    * @return JD Today's Julian Date
    */
VirtualtelescopeAssistant.prototype.julian_date = function(now_time_tm_year,now_time_tm_mon,now_time_tm_day,now_time_tm_hour,now_time_tm_min,now_time_tm_sec)
{
    var year=now_time_tm_year;
    var month=now_time_tm_mon+1;
    var day=now_time_tm_day;
    var UT=now_time_tm_hour+now_time_tm_min/60.0+now_time_tm_sec/3600.0;
    var JD=367*year-this.toInt(7.0*(year+this.toInt((month+9.0)/12.0))/4.0)-
        this.toInt(3.0*(this.toInt((year+(month-9.0)/7.0)/100.0)+1.0)/4.0)+
        this.toInt(275.0*month/9.0)+day+1721028.5+UT/24.0;
    return(JD);
}
/** Converts input to integer.
 * @param nmb Any number.
 * @return nmb The given number as an integer.
 */
VirtualtelescopeAssistant.prototype.toInt = function(nmb)
{
    if(nmb>0)
        return Math.floor(nmb);
    if(nmb<0)
        return Math.ceil(nmb);
    return nmb;
}
/** Finds the day of the year
 * @param Y year
 * @param M month
 * @param D day
 * @return The day of the year in seconds from the first of the year
 */
VirtualtelescopeAssistant.prototype.FDoY = function(Y,M,D)
{
    return(Date.UTC(Y,M,D)-Date.UTC(Y,1,1))/86400000+1;
}